#include <string.h>
#include <Includes.h>
#include <DRV_Usart.h>
//#include <DRV_Nb.h>
#include <DRV_Neul.h>
//#include <DRV_Bc28.h>
#include <DRV_EC600S.h>
#include <OPP_Debug.h>

typedef struct
{
   EN_DEV_TYPE type;
   int (*UrcMsgProc)(char *inBuffer,int bufLen);
}ST_NEUL;

ST_NEUL g_stNeul[EN_DEV_TYPE_MAX]=
{
    {EN_DEV_TYPE_EC600S,Ec600sUrcMsgProc},
};

static T_MUTEX  g_stRxMutex;

int NeulInit()
{
	MUTEX_CREATE(g_stRxMutex);
    return 0;
}

//extern SemaphoreHandle_t g_NbRxSem;

int uart_data_read(char *buf, int maxrlen, int mode, int timeout)
{
	int retlen = 0;

    if (NULL == buf || maxrlen <= 0 || timeout < 0)
    {
		DEBUG_LOG(DEBUG_MODULE_EC600S, DLL_ERROR, "%s %d\r\n", __FUNCTION__, __LINE__);
        return 0;
    }
	//while(1){
	    //noted by wangtao
		/*BaseType_t r = OS_SEMAPHORE_TAKE(g_NbRxSem,timeout);
		if (r == pdFALSE){
			//printf("uart_data_read take sem timeout\r\n");
			return -1;
		}*/
		retlen = uart_read_bytes(&usart1_context,(U8 *)buf, maxrlen, timeout);
		if(retlen>0){
			//printf("uart_data_read: %s\r\n", buf);
			return retlen;
		}
	//}

    return retlen;
}

//static int uart_data_write(const char *buf, int writelen, int mode)
int uart_data_write(char *buf, int writelen, int mode)
{
	int ret;

    if (NULL == buf || writelen <= 0)
    {
        return 0;
    }
    ret = uart_write_bytes(&usart1_context,buf, writelen);
    return ret;
}

int NeulDataRead(EN_DEV_TYPE type, char *buf, int maxrlen, int mode, unsigned int timeout)
{
	static U32 startTick,reStartTick;
	U32 time, time1;
	int rlen, rlen1 = 0;
	char tmpBuf[NEUL_MAX_BUF_SIZE] = {0};
	/*
	1.串口收数据
	2.URC消息处理
	*/
	MUTEX_LOCK(g_stRxMutex,MUTEX_WAIT_ALWAYS);
	startTick = OppTickCountGet();
	while(1){
		reStartTick = OppTickCountGet();
		time1 = (reStartTick - startTick);
		time = (timeout>time1)?(timeout - time1):0;
		if(time == 0){
			//printf("break tick %d\r\n", reStartTick);
			break;
		}
		rlen = uart_data_read(tmpBuf, NEUL_MAX_BUF_SIZE, mode, time);
		if(rlen > 0){
			//printf("uart_data_read rlen %d\r\n", rlen);
			//printf("%s", tmpBuf);
			rlen1 = g_stNeul[type].UrcMsgProc(tmpBuf, rlen);
			if(rlen1 == 0) //only urc
			{
				//printf("UrcMsgProc rlen1 = 0 tick %d\r\n", OppTickCountGet());
				continue;
			}
			else if(rlen1 > 0) //not only urc
			{
				break;
			}
		}

	}
	memcpy(buf,tmpBuf,rlen1);
	MUTEX_UNLOCK(g_stRxMutex);
	return rlen1;
}


/**
@brief EC600S接收数据接口
@return 0成功，非0失败
**/
int Ec600sDataRead(char *buf, int maxrlen, int mode, unsigned int timeout)
{
    return NeulDataRead(EN_DEV_TYPE_EC600S, buf, maxrlen, mode, timeout);
}

/**
@brief EC600S接收数据处理,被EC600S任务调用
@return 0成功，非0失败
**/
void Ec600sRxDataProc()
{
	char outbuf[NEUL_MAX_BUF_SIZE] = {0};
	Ec600sDataRead(outbuf, NEUL_MAX_BUF_SIZE, 0, 10);
}

/**
@brief convert char to hex string
@param bufin the data that need to convert
@param len data length
@param bufout hex string data
@return 0成功，非0失败
**/
int NeulBc28HexToStr(const unsigned char *bufin, int len, char *bufout)
{
    int i = 0;
    #if 0
    int tmp = 0;
    #endif
    if (NULL == bufin || len <= 0 || NULL == bufout)
    {
        return -1;
    }
    for(i = 0; i < len; i++)
    {
        #if 0
        tmp = bufin[i]>>4;
        bufout[i*2] = tmp > 0x09?tmp+0x37:tmp+0x30;
        tmp = bufin[i]&0x0F;
        bufout[i*2+1] = tmp > 0x09?tmp+0x37:tmp+0x30;
        #else
        sprintf(bufout+i*2, "%02X", bufin[i]);
        #endif
    }
    return 0;
}

/**
@brief convert hex string to hex data
@param bufin the data that need to convert
@param len data length
@param bufout hex data after convert
@return 0成功，非0失败
**/
int NeulBc28StrToHex(const char *bufin, int len, char *bufout)
{
    int i = 0;
    unsigned char tmp2 = 0x0;
    unsigned int tmp = 0;
    if (NULL == bufin || len <= 0 || NULL == bufout)
    {
        return -1;
    }
    for(i = 0; i < len; i = i+2)
    {
        #if 1
        tmp2 =  bufin[i];
        tmp2 =  tmp2 <= '9'?tmp2-0x30:tmp2-0x37;
        tmp =  bufin[i+1];
        tmp =  tmp <= '9'?tmp-0x30:tmp-0x37;
        bufout[i/2] =(tmp2<<4)|(tmp&0x0F);
        #else
        sscanf(bufin+i, "%02x", &tmp);
        bufout[i/2] = tmp;
        #endif
    }
    return 0;
}

/**
@brief 获取当前设备状态
@param
@return 设备状态
**/
int NeulDevStGet()
{
    #if (DEV_USED==DEV_EC600S)
        return Ec600sStGet();
    #endif

    return -1;
}

/**
@brief 获取当前设备是否就绪
@param
@return true就绪,flase未就绪
**/
bool NeulDevIsReady()
{
    #if (DEV_USED==DEV_EC600S)
        if(EC600S_DEV_READY == Ec600sStGet())
        {
            return true;
        }
    #endif

    return false;
}

/**
@brief csq转换为rssi,gsm模式下由csq获取rssi,其他直接参考rsrp
@param csq 通过AT+CSQ获取的csq
@return rssi
**/
int Csq2Rssi(unsigned char csq)
{
    int rssi=2*csq - 113;
    return rssi;
}

/**
@brief LTE sinr转snr.Range: 0-250, which translates to -20dB - +30dB
@param sinr 通过AT+QENG获取的sinr
@return snr
**/
int Sinr2Snr(unsigned char sinr)
{
    return sinr/5-20;
}

